package com.wpi.iCoach;

import java.util.Comparator;

/**
 * This class represents a location. It is primarily used to organize a list
 * of such locations by providing camparator functions. This functions are
 * in-turn used to set the sorted order of these lists.  
 * 
 * @author Kenneth J. Loomis (kjloomis)
 * @version June 2012
 */
public class LocationEntry implements Comparable<LocationEntry> {

	/** The name of the location. */
	public String locName;
	
	/** A text representation of the distance from the user's current location. */
	public String dist;
	
	/** The latitude position of the location. */
	public double lat;
	
	/** The longitude position of the location. */
	public double lon;
	
	/** The numerical distance from the user's current location. */
	public double distance;
	
	/** The number of visits made by the user to this location. */
	public int visit;
	
	/** The value representing the rank of the location (0 to 5). */
	public float likeness;
	
	/**
	 * An enum map used to identify the comparator to use to compare
	 * two LocationEntry.
	 */
	public enum LEComparator implements Comparator <LocationEntry>
	{

		/** Compare by distance to the user's current location. */
		DISTANCE {
			public int compare(LocationEntry lhs, LocationEntry rhs) { 
				return (int) ( ( lhs.distance -  rhs.distance ) * 1E6 ) ;
			}
		},
		/** Compare by location name (Ascending). */
		ALPHA_DESC {
			public int compare(LocationEntry lhs, LocationEntry rhs) {
				return ( lhs.locName.compareTo (rhs.locName ) ) ;
			}
		},
		/** Compare by location name (Descending). */
		ALPHA_ASC {
			public int compare(LocationEntry lhs, LocationEntry rhs) {
				return ( rhs.locName.compareTo (lhs.locName ) ) ;
			}
		},
		/** Compare by location ranking (Descending). */
		RANK {
			public int compare(LocationEntry lhs, LocationEntry rhs) {
				return (int) ( ( rhs.likeness -  lhs.likeness ) * 1E6 ) ;
			}
		},
		/** Compare by number of visits (Descending). */
		VISIT {
			public int compare(LocationEntry lhs, LocationEntry rhs) {
				return ( rhs.visit - lhs.visit ) ;
			}
		};

	}

	/**
	 * Constructor. Create a LocationEntry by providing the required information.
	 * @param lat (Location latitude.)
	 * @param lon (Location longitude.)
	 * @param name (Location name.)
	 * @param dist (Distance from user's current location.)
	 * @param visit (The number of recorded visits to this location.)
	 * @param like (The rank of this location.)
	 */
	public LocationEntry ( double lat, double lon, String name, double dist, int visit, float like )
	{
		this.lat = lat;
		this.lon = lon;
		this.locName = name;
		this.distance = dist;
		this.visit = visit;
		this.likeness = like;
		this.dist = String.format( "%.1f", dist ) + " mi";
	}

	/**
	 * Returns the comparator function that corresponds to the provided
	 * integer values. The integer value is defined by the position in the
	 * drop-down spinner selector for the sort by option. Invalid comp
	 * values result in using the default sort by distance option.
	 * @param comp (An integer representation of the comparator.) 
	 * @return Comparator function
	 */
	public static Comparator<LocationEntry> getComparator( int comp )
	{
		switch ( comp )
		{
			case 0: return LEComparator.DISTANCE;
			case 1: return LEComparator.ALPHA_DESC;
			case 2: return LEComparator.ALPHA_ASC;
			case 3: return LEComparator.RANK;
			case 4: return LEComparator.VISIT;
		}
		return LEComparator.DISTANCE;
	}

	/**
	 * The default comparator which sorts by the locations' distance from the
	 * user's current location.
	 * @param another (The location which to compare to.)
	 * @return An integer representing how similar the two location are. A negative number
	 * means the other location is farther away from the user. A positive number means the 
	 * other location is closer to the user. Zero means the two locations are equidistant
	 * to the user location.
	 */
	@Override
	public int compareTo(LocationEntry another) {
		return (int) ( ( distance -  ( ( LocationEntry )another ).distance ) * 1E6 ) ;
	}
	  
}
